#include "wl_file.h"
#include "wl_trace.h"
#include <stdlib.h>
#include "ql_fs.h"

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

static wl_char* wl_getQuactelPath(const wl_char *path) {
    if (path) {
        int len = strlen(path);
        wl_char *p_temp = (wl_char *)malloc(len + 4);
        if (p_temp) {
            memset(p_temp, 0, len + 4);
            sprintf(p_temp, "U:/%s", path);
            return p_temp;
        }
    }

    return NULL;
}

wl_int32 wl_mkdir(const wl_char* path) {
    int ret = LFS_ERR_OK;

    if (path) {
        wl_char *p_temp = wl_getQuactelPath(path);
        if (p_temp) {
            ret = ql_mkdir(p_temp, 0);
            free(p_temp);            
        }else {
            ret = LFS_ERR_NOMEM;
        }
    }else {
        ret = LFS_ERR_INVAL;
    }

    return ret;
}

wl_int32 wl_rmdir(const wl_char* path) {
    int ret = LFS_ERR_OK;
    if (path) {
        wl_char *p_temp = wl_getQuactelPath(path);
        if (p_temp) {
            QDIR *dir = ql_opendir(p_temp);
            if (dir) {       
                struct lfs_info info;
                memset(&info, 0, sizeof(struct lfs_info));
                while(ql_readdir(dir, &info) == LFS_ERR_OK) {
                    if (info.type == LFS_TYPE_DIR) {
                        wl_mkdir(info.name);
                    }else {
                        ql_remove(info.name);
                    }
                }

                ql_remove(p_temp);
                ret = ql_closedir(dir);
            }else {
                ret = LFS_ERR_NOENT;
            }

            free(p_temp);
        }else {
            ret = LFS_ERR_NOMEM;
        }
    }else {
        ret = LFS_ERR_INVAL;
    }
    

    return ret;
}

wl_int32 wl_remove(const wl_char* path) {
    int ret = LFS_ERR_OK;
    if (path) {
        wl_char *p_temp = wl_getQuactelPath(path);
        if (p_temp) {
            ret = ql_remove(p_temp);
            free(p_temp);
        }else {
            ret = LFS_ERR_NOMEM;
        }
    }else {
        ret = LFS_ERR_INVAL;
    }
    
    return ret;
}

wl_int32 wl_rename(const wl_char* src_path, const wl_char* dst_path) {
    int ret = LFS_ERR_OK;
    if (src_path && dst_path) {
        wl_char *p_temp_src = wl_getQuactelPath(src_path);
        wl_char *p_temp_dst = wl_getQuactelPath(dst_path);
        if (p_temp_dst && p_temp_src) {
            ret = ql_rename(p_temp_src, p_temp_dst);;
        }else {
            ret = LFS_ERR_NOMEM;
        }

        if (p_temp_src) {
            free(p_temp_src);
        }
        
        if (p_temp_dst) {
            free(p_temp_dst);
        }
    }else {
        ret = LFS_ERR_INVAL;
    }
    
    return ret;
}

wl_int32 wl_access(const wl_char* path, wl_int32 mode) {
    int ret = LFS_ERR_OK;
    if (path) {
        wl_char *p_temp = wl_getQuactelPath(path);
        if (p_temp) {
            ret = ql_access(p_temp, mode);
            free(p_temp);
        }else {
            ret = LFS_ERR_NOMEM;
        }
    }else {
        ret = LFS_ERR_INVAL;
    }
    
    return ret;
}

WL_FHANDLE wl_fopen(const wl_char* path, wl_int32 flags) {
    char *pOpenMode;
    WL_FHANDLE h = WL_INVALID_FHANDLE;
    if (path) {
        wl_char *p_temp = wl_getQuactelPath(path);
        WLLOGD("wl_fopen filename:%s", p_temp);
        if (!p_temp) {
            return h;
        }

        if (flags & WL_CREAT) {
            pOpenMode = "wb+";
        }else if (flags & WL_RDWR) {
            pOpenMode = "rb+";
        }else if (flags & WL_RDONLY) {
            pOpenMode = "rb";
        }else if (flags & WL_WRONLY) {
            pOpenMode = "wb";
        }else if (flags & WL_APPEND) {
            pOpenMode = "a+";
        }else {
            free(p_temp);
            return WL_INVALID_FHANDLE;
        }

        h = ql_fopen(p_temp, pOpenMode);
        free(p_temp);
    }

    return h;
}

wl_int32 wl_fread(WL_FHANDLE fhandle, OUT void* buf, wl_uint32 count) {
    QFILE *pFile = fhandle;
    return ql_fread(buf, 1, count, pFile);
}

wl_int32 wl_fwrite(WL_FHANDLE fhandle, void* buf, wl_uint32 count) {
    QFILE *pFile = fhandle;
    return ql_fwrite(buf, 1, count, pFile);
}

wl_int32 wl_fclose(WL_FHANDLE fhandle) {
    QFILE *pFile = fhandle;
    return ql_fclose(pFile);
}

wl_int32 wl_fseek(WL_FHANDLE fhandle, wl_int32 offset, wl_int32 whence) {
    QFILE *pFile = fhandle;
    return ql_fseek(pFile, offset, whence);
}

wl_ssize wl_fsize(WL_FHANDLE fhandle) {
    QFILE *pFile = fhandle;
    return ql_fsize(pFile);
}

#ifdef __cplusplus
}
#endif /* __cplusplus */
